#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gevent import monkey
monkey.patch_socket()
from gevent import Greenlet
import Singleton
import ThreadSafeSingletion
import ConfigFileData
import SocketTools
import logging
import socket
import time
from pageType import *
import pq_quota_pb2
import PreMkt_Protocol_pb2


@Singleton.singleton
class Connection(Greenlet):
    def __init__(self):
        Greenlet.__init__(self)
        self.queue = ThreadSafeSingletion.SafeQueue()
        self.requesetId = 0
        self.config = ConfigFileData.Data()
        self.packTools = SocketTools.StructProtocol()
        self.RebuildConnection(self.config.get(u'PreMkt.ip'), int(self.config.get(u'PreMkt.port')))

    def RebuildConnection(self, ip, port):
        while True:
            try:
                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.sock.connect((ip, port))
            except:
                logging.warning(u"PreMkt连接失败, 等待5秒后重新尝试...")
                time.sleep(5)
                continue
            self.PreQuoSubMsg()
            break


    def Recv(self, Packlen):
        ret = str()
        while 1:
            recvBuf = self.sock.recv(Packlen-len(ret))
            if len(recvBuf) == Packlen-len(ret):
                ret += recvBuf
                break
            ret += recvBuf
        return ret

    def RequesetId(self):
        self.requesetId += 1
        return str(self.requesetId)

    def _run(self):
        print '[Start]PreMarket'
        switch = {
            LYMK_MARKET_OVERVIEW: self.MarketOverview,
            LYMK_ETF_BASE_INFO: self.EtfBaseInfo,
            LYMK_FJJJ_INFOR: self.FjjjInfor,
            LYMK_STRUCTURED_FUND_BASE: self.Structured_fund,
            LYMK_ETF_DIFF_INFO: self.EtfDiffInfo,
            LYMK_TRADEDAY_INFO: self.TradeDay,
            LYMK_HEARTBEAT: self.Heart,
            LYMK_HEARTBEAT_REQ: self.Heart
        }

        while True:
            try:
                header = self.Recv(self.packTools.getHeaderLen())
                body = self.Recv(self.packTools.GetBodyLen(header))
                self.packTools.putData(header+body)
            except socket.error, e:
                # logging.warning(u"PreMkt.recv 发生错误:{0}, 重新建立连接...".format(e))
                self.RebuildConnection(self.config.get(u'PreMkt.ip'), int(self.config.get(u'PreMkt.port')))
                continue
            except:
                logging.warning(u"PreMkt:_run:发生未知错误。")
                exit(-1)

            while 1:
                data = self.packTools.getOnce()
                if data:
                    pType = data['head'][2]
                    try:
                        switch[int(pType)](message=data)
                    except:
                        logging.warning(u"premkt处理行情包子类型：{0} 发生错误。".format(pType))
                else:
                    break

    def MarketOverview(self, **kwargs):
        message = kwargs['message']['body']
        market = pq_quota_pb2.MarketDaily()
        market.ParseFromString(message)
        self.queue.put([u'MarketOverview', market, kwargs['message']['head'][3]])

    def EtfBaseInfo(self, **kwargs):
        message = kwargs['message']['body']
        market = pq_quota_pb2.EtfBasketInfo()
        market.ParseFromString(message)
        self.queue.put([u'EtfBasketInfo', market, kwargs['message']['head'][3]])

    def FjjjInfor(self, **kwargs):
        message = kwargs['message']['body']
        market = pq_quota_pb2.StructuredFundInfo()
        market.ParseFromString(message)
        self.queue.put([u'StructuredFundInfo', market, kwargs['message']['head'][3]])

    def Structured_fund(self, **kwargs):
        message = kwargs['message']['body']
        market = PreMkt_Protocol_pb2.structured_fund()
        market.ParseFromString(message)
        self.queue.put([u'structured_fund', market, kwargs['message']['head'][3]])

    def EtfDiffInfo(self, **kwargs):
        message = kwargs['message']['body']
        market = pq_quota_pb2.EtfListDiff()
        market.ParseFromString(message)
        self.queue.put([u'EtfListDiff', market, kwargs['message']['head'][3]])

    def TradeDay(self, **kwargs):
        message = kwargs['message']['body']
        market = pq_quota_pb2.TradedayMsg()
        market.ParseFromString(message)
        self.queue.put([u'TradedayMsg', market, kwargs['message']['head'][3]])

    def PreQuoSubMsg(self, sub_flag=1):
        msg = pq_quota_pb2.PreQuoSubMsg()
        msg.sub_flag = sub_flag
        msg.sub_type.append(LYMK_ETF_BASE_INFO)
        msg.sub_type.append(LYMK_MARKET_OVERVIEW)
        msg.sub_type.append(LYMK_ETF_DIFF_INFO)
        msg.sub_type.append(LYMK_FJJJ_INFOR)
        msg.sub_type.append(LYMK_STRUCTURED_FUND_BASE)
        req = msg.SerializeToString()
        data = self.packTools.pack([len(req), MODULE_NUMBER_MARKET, LYMK_PRE_QUO_SUB, self.RequesetId()], req)
        self.sock.sendall(data)

    def Heart(self, **kwargs):
        data = self.packTools.pack([0, MODULE_NUMBER_MARKET, LYMK_HEARTBEAT, self.RequesetId()], '')
        self.sock.sendall(data)